#include "LeCompteEstBon.h"

LeCompteEstBon::LeCompteEstBon(QWidget *parent) : QMainWindow(parent)
{
    QWidget* ptWidget = new QWidget;
    setCentralWidget(ptWidget);

    for(int i = 0; i < 6; i++)
    {
        m_ptIntButton[i] = new QPushButton(tr("-"));
        m_ptIntButton[i]->setEnabled(false);
        connect(m_ptIntButton[i], SIGNAL(clicked()), this, SLOT(selectInteger()));
    }

    QLabel* ptEqualLabel[5];
    for(int i = 0; i < 5; i++)
    {
        m_aResult[i].ptDelButton = new QPushButton(tr("Del"));
        m_aResult[i].ptDelButton->setEnabled(false);
        connect(m_aResult[i].ptDelButton, SIGNAL(clicked()), this, SLOT(deleteResult()));

        m_aResult[i].ptResultButton = new QPushButton(tr("-"));
        m_aResult[i].ptResultButton->setEnabled(false);
        connect(m_aResult[i].ptResultButton, SIGNAL(clicked()), this, SLOT(selectInteger()));

        m_aResult[i].ptResultLabel = new QLabel;
        m_aResult[i].ptResultLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
        m_aResult[i].ptResultLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);

        m_aResult[i].ptButtonA = NULL;
        m_aResult[i].ptButtonB = NULL;
        m_aResult[i].cOperation = '\0';

        ptEqualLabel[i] = new QLabel;
        ptEqualLabel[i]->setFrameStyle(QFrame::NoFrame);
        ptEqualLabel[i]->setText("=");
        ptEqualLabel[i]->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
    }

    QPushButton* ptAddButton = new QPushButton(tr("+"));
    connect(ptAddButton, SIGNAL(clicked()), this, SLOT(selectOperation()));

    QPushButton* ptMulButton = new QPushButton(tr("*"));
    connect(ptMulButton, SIGNAL(clicked()), this, SLOT(selectOperation()));

    QPushButton* ptDivButton = new QPushButton(tr("/"));
    connect(ptDivButton, SIGNAL(clicked()), this, SLOT(selectOperation()));

    QPushButton* ptSubButton = new QPushButton(tr("-"));
    connect(ptSubButton, SIGNAL(clicked()), this, SLOT(selectOperation()));

    m_ptTimerBar = new QProgressBar;
    m_ptTimerBar->setRange(0, 45);
    m_ptTimerBar->setTextVisible(false);
    m_ptTimerLabel = new QLabel;
    m_ptTimerLabel->setFrameStyle(QFrame::NoFrame);
    m_ptTimerLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
    setTime(0);

    m_ptResultToFindLabel = new QLabel;
    m_ptResultToFindLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);

    QGridLayout* ptLayout = new QGridLayout;

    for(int i = 0; i < 8; i++)
    {
        ptLayout->setColumnStretch(i, 1);
    }

    ptLayout->addWidget(m_ptIntButton[0], 0, 0, 1, 3);
    ptLayout->addWidget(m_ptIntButton[1], 0, 3, 1, 3);
    ptLayout->addWidget(m_ptIntButton[2], 0, 6, 1, 3);
    ptLayout->addWidget(ptAddButton, 0, 12, 1, 3);
    ptLayout->addWidget(ptSubButton, 0, 15, 1, 3);

    ptLayout->addWidget(m_ptIntButton[3], 1, 0, 1, 3);
    ptLayout->addWidget(m_ptIntButton[4], 1, 3, 1, 3);
    ptLayout->addWidget(m_ptIntButton[5], 1, 6, 1, 3);
    ptLayout->addWidget(ptMulButton, 1, 12, 1, 3);
    ptLayout->addWidget(ptDivButton, 1, 15, 1, 3);

    for(int i = 0; i < 5; i++)
    {
        ptLayout->addWidget(m_aResult[i].ptDelButton, i + 2, 0, 1, 1);
        ptLayout->addWidget(m_aResult[i].ptResultLabel, i + 2, 1, 1, 6);
        ptLayout->addWidget(ptEqualLabel[i], i + 2, 7, 1, 2);
        ptLayout->addWidget(m_aResult[i].ptResultButton, i + 2, 9, 1, 3);
    }

    ptLayout->addWidget(m_ptResultToFindLabel, 3, 14, 1, 2);
    ptLayout->addWidget(m_ptTimerBar, 4, 12, 1, 6);
    ptLayout->addWidget(m_ptTimerLabel, 4, 14, 1, 2);

    ptWidget->setLayout(ptLayout);

    menuBar()->setNativeMenuBar(false);

    QMenu* ptMenu = menuBar()->addMenu(tr("&File"));

    QAction* ptAction = new QAction(tr("&New Game"), this);
    ptAction->setStatusTip(tr("Start a new game"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(newGame()));
    ptMenu->addAction(ptAction);

    ptAction = new QAction(tr("&Find solution"), this);
    ptAction->setStatusTip(tr("Find a solution to a known set of integers"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(findSolution()));
    ptMenu->addAction(ptAction);

    ptAction = new QAction(tr("&Generate and Find"), this);
    ptAction->setStatusTip(tr("Generate a random set of integers and find a solution to this set"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(generateAndFindSolution()));
    ptMenu->addAction(ptAction);

    ptMenu->addSeparator();

    ptAction = new QAction(tr("&Exit"), this);
    ptAction->setStatusTip(tr("Exit the game"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(exit()));
    ptMenu->addAction(ptAction);

    ptMenu = menuBar()->addMenu(tr("&Help"));

    ptAction = new QAction(tr("&About"), this);
    ptAction->setStatusTip(tr("Informations about this program and the game's rules"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(about()));
    ptMenu->addAction(ptAction);

    ptAction = new QAction(tr("About &Qt"), this);
    ptAction->setStatusTip(tr("Informations about Qt"));
    connect(ptAction, SIGNAL(triggered()), this, SLOT(aboutQt()));
    ptMenu->addAction(ptAction);

    setWindowTitle(tr("Le compte est bon"));

    m_currentOperation.iA = -1;
    m_currentOperation.iB = -1;
    m_currentOperation.ptButtonA = NULL;
    m_currentOperation.ptButtonB = NULL;
    m_currentOperation.cOperation = '\0';

    m_bIsGameStarted = false;
    m_bIsGameDataAvailable = false;

    m_ptIdleTimer = new QTimer;
    connect(m_ptIdleTimer, SIGNAL(timeout()), this, SLOT(checkGameData()));
}

LeCompteEstBon::~LeCompteEstBon()
{

}

void LeCompteEstBon::selectInteger()
{
    if(m_bIsGameStarted)
    {
        QPushButton* ptClickedButton = qobject_cast<QPushButton*> (sender());
        int iDigitValue = ptClickedButton->text().toInt();

        if(ptClickedButton->isEnabled())
        {
            if(m_currentOperation.cOperation == '\0')
            {
                if(m_currentOperation.iA != -1)
                {
                    m_currentOperation.ptButtonA->setEnabled(true);

                    m_currentOperation.iA = -1;
                    m_currentOperation.ptButtonA = NULL;
                }

                m_currentOperation.iA = iDigitValue;
                m_currentOperation.ptButtonA = ptClickedButton;
                ptClickedButton->setEnabled(false);
            }
            else
            {
                m_currentOperation.iB = iDigitValue;
                m_currentOperation.ptButtonB = ptClickedButton;
                ptClickedButton->setEnabled(false);
                //TODO send operation to TheGame
                if(m_game.addOperation(m_currentOperation))
                {
                    addResult(m_currentOperation);
                }
                else
                {
                    m_currentOperation.ptButtonA->setEnabled(true);
                    m_currentOperation.ptButtonB->setEnabled(true);
                }

                m_currentOperation.iA = -1;
                m_currentOperation.iB = -1;
                m_currentOperation.ptButtonA = NULL;
                m_currentOperation.ptButtonB = NULL;
                m_currentOperation.cOperation = '\0';
            }
        }
    }
}

void LeCompteEstBon::selectOperation()
{
    if(m_bIsGameStarted)
    {
        QPushButton* ptClickedButton = qobject_cast<QPushButton*> (sender());
        QString szStringValue = ptClickedButton->text();

        if(ptClickedButton->isEnabled())
        {
            if(m_currentOperation.iA != -1)
            {
                m_currentOperation.cOperation = szStringValue[0].toAscii();
            }
            else
            {
                //TODO Error
            }
        }
    }
}

void LeCompteEstBon::newGame()
{
    T_GameSet gameSet = m_game.generateAndGetNumbers();

    for(int i = 0; i < 6; i++)
    {
        m_ptIntButton[i]->setText(QString::number(gameSet.aiTab[i]));
        m_ptIntButton[i]->setEnabled(true);
    }

    for(int i = 0; i < 5; i++)
    {
        m_aResult[i].ptResultLabel->setText(tr(""));
        m_aResult[i].ptResultButton->setText(tr("-"));
        m_aResult[i].ptResultButton->setEnabled(false);
        m_aResult[i].ptDelButton->setEnabled(false);
    }

    m_ptResultToFindLabel->setText(QString::number(gameSet.iResult));

    m_bIsGameStarted = true;
    m_ptIdleTimer->start();
}

void LeCompteEstBon::findSolution()
{

}

void LeCompteEstBon::generateAndFindSolution()
{

}

void LeCompteEstBon::exit()
{

}

void LeCompteEstBon::about()
{

}

void LeCompteEstBon::aboutQt()
{

}

void LeCompteEstBon::setTime(int _iSeconds)
{
    m_ptTimerBar->setValue(_iSeconds);
    m_ptTimerLabel->setText(QString::number(_iSeconds));
}

void LeCompteEstBon::addResult(const T_QtOperation& _operation)
{
    bool bIsResultAdded = false;

    for(int i = 0; i < 5 && !bIsResultAdded; i++)
    {
        if(m_aResult[i].ptResultButton->text() == "-")
        {
            int iResult = Solver::getResultForOperation(_operation);

            m_aResult[i].ptDelButton->setEnabled(true);
            m_aResult[i].ptResultButton->setEnabled(true);
            m_aResult[i].ptResultButton->setText(QString::number(iResult));
            m_aResult[i].ptResultLabel->setText(tr(Solver::getStringForOperationWithoutResult(_operation).c_str()));
            m_aResult[i].ptButtonA = _operation.ptButtonA;
            m_aResult[i].ptButtonB = _operation.ptButtonB;
            m_aResult[i].cOperation = _operation.cOperation;

            for(int j = 0; j < 5; j++)
            {
                if(m_aResult[i].ptButtonA == m_aResult[j].ptResultButton || m_aResult[i].ptButtonB == m_aResult[j].ptResultButton)
                {
                    m_aResult[j].ptDelButton->setEnabled(false);
                }
            }

            bIsResultAdded = true;
        }
    }
}

void LeCompteEstBon::deleteResult()
{
    if(m_bIsGameStarted)
    {
        QPushButton* ptClickedButton = qobject_cast<QPushButton*> (sender());

        if(ptClickedButton->isEnabled())
        {
            for(int i = 0; i < 5; i++)
            {
                if(m_aResult[i].ptDelButton == ptClickedButton)
                {
                    T_Operation operation;

                    operation.cOperation = m_aResult[i].cOperation;

                    if(m_aResult[i].ptButtonA)
                    {
                        operation.iA = m_aResult[i].ptButtonA->text().toInt();
                    }
                    else
                    {
                        operation.iA = -1;
                    }

                    if(m_aResult[i].ptButtonB)
                    {
                        operation.iB =  m_aResult[i].ptButtonB->text().toInt();
                    }
                    else
                    {
                        operation.iB = -1;
                    }

                    if(m_game.delOperation(operation))
                    {
                        m_aResult[i].ptDelButton->setEnabled(false);
                        m_aResult[i].ptResultButton->setEnabled(false);
                        m_aResult[i].ptResultButton->setText(tr("-"));
                        m_aResult[i].ptResultLabel->setText(tr(""));

                        if(m_aResult[i].ptButtonA)
                        {
                            m_aResult[i].ptButtonA->setEnabled(true);
                        }
                        if(m_aResult[i].ptButtonB)
                        {
                            m_aResult[i].ptButtonB->setEnabled(true);
                        }

                        for(int j = 0; j < 5; j++)
                        {
                            if(m_aResult[i].ptButtonA == m_aResult[j].ptResultButton || m_aResult[i].ptButtonB == m_aResult[j].ptResultButton)
                            {
                                m_aResult[j].ptDelButton->setEnabled(true);
                            }
                        }

                        m_aResult[i].ptButtonA = NULL;
                        m_aResult[i].ptButtonB = NULL;


                        for(int j = i; j < 4; j++)
                        {
                            m_aResult[j].ptDelButton->setEnabled(m_aResult[j + 1].ptDelButton->isEnabled());
                            m_aResult[j].ptResultButton->setEnabled(m_aResult[j + 1].ptResultButton->isEnabled());
                            m_aResult[j].ptResultButton->setText(m_aResult[j + 1].ptResultButton->text());
                            m_aResult[j].ptResultLabel->setText(m_aResult[j + 1].ptResultLabel->text());
                            m_aResult[j].ptButtonA = m_aResult[j + 1].ptButtonA;
                            m_aResult[j].ptButtonB = m_aResult[j + 1].ptButtonB;

                            if(m_aResult[j].ptButtonA)
                            {
                                m_aResult[j].ptButtonA->setEnabled(true);
                            }
                            if(m_aResult[j].ptButtonB)
                            {
                                m_aResult[j].ptButtonB->setEnabled(true);
                            }

                            m_aResult[j + 1].ptDelButton->setEnabled(false);
                            m_aResult[j + 1].ptResultButton->setEnabled(false);
                            m_aResult[j + 1].ptResultButton->setText(tr("-"));
                            m_aResult[j + 1].ptResultLabel->setText(tr(""));
                            m_aResult[j + 1].ptButtonA = NULL;
                            m_aResult[j + 1].ptButtonB = NULL;
                        }
                    }
                }
            }
        }
    }
}

void LeCompteEstBon::stopTheGame()
{
    m_bIsGameStarted = false;
    m_ptIdleTimer->stop();

    for(int i = 0; i < 6; i++)
    {
        m_ptIntButton[i]->setEnabled(false);
    }

    for(int i = 0; i < 5; i++)
    {
        m_aResult[i].ptDelButton->setEnabled(false);
        m_aResult[i].ptResultButton->setEnabled(false);
    }
}

void LeCompteEstBon::checkGameData()
{
    if(m_game.isPoolDataAvailable())
    {
        T_GameState gameState = m_game.localPoolPop();

        if(gameState.iTimeRemaining != m_ptTimerBar->value())
        {
            setTime(gameState.iTimeRemaining);
            m_ptTimerBar->repaint();
        }

        if(gameState.bIsGameFinished)
        {
            stopTheGame();

            if(gameState.bIsGameWon)
            {
                QMessageBox msgBox;
                msgBox.setText(tr("GG !"));
                msgBox.exec();
            }
            else
            {
                QMessageBox msgBox;
                msgBox.setText(tr("BOUH !"));
                msgBox.exec();
            }
        }
    }
}
